<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>生成器Gererator的用法</title>
</head>
<body>

</body>

<script type="text/javascript">
  
  // Generate函数：可以通过yield关键字将函数挂起，为了改变执行流提供了可能，同时为了做异步编程提供了方案
  // 跟普通函数的区别
  // 1、function后面 函数名之前有个*，通常写成 function*
  // 2、只能在函数内部使用yield表达式，让函数挂起
  function* func(params) {
    yield 2
    yield 3
  }
  // 返回一个遍历器对象，可以调用next()
  let fn = func()
  console.log(fn);

  console.log(fn.next());
  console.log(fn.next());
  console.log(fn.next());

  // 总结：Generator函数是分段执行的，yield语句是暂停执行，而next()恢复执行
  function* add() {
    console.log('start')
    let x = yield '2'
    console.log('one:', x);
    let y = yield '3'
    console.log('two:', y);
    return x + y
  }
  const fn1 = add()
  console.log(fn1.next());
  console.log(fn1.next(20));
  console.log(fn1.next(30));

  // 使用场景：为不具备Iterator接口的对象提供了遍历操作
  function* objectEntries(obj) {
    // 获取对象的所有key保存到数组【name，age】
    const propKeys = Object.keys(obj)
    for (const propKey of propKeys) {
      yield [propKey, obj[propKey]]
    }
  }

  const obj = {
    name: 'chengjunyu',
    age: 30
  }

  obj[Symbol.iterator] = objectEntries
  console.log(obj);

  for(let [key, value] of objectEntries(obj)) {
    console.log(key, value);
  }

  function* load() {
    loadUi()
    yield showData()
    hideUi()
  }

  let isLoad = load()
  isLoad.next()


  // 执行顺序
  function loadUi() {
    console.log('加载loading页面');
  }

  function showData() {
    setTimeout(() => {
      console.log('数据加载完成');
      isLoad.next()
    }, 3000)
  }


  function hideUi() {
    console.log('隐藏loading页面');
  }

  // loadUi()
  // showData()
  // hideUi()


</script>
</html>